//
// Created by F1997 on 2024/10/21.
//

#include "PcapUtils.h"
#include "headers.hpp"

#define HOME_DIR "/tmp/tmp.2SNBTi3J7e/"

// ========== socket

// 发送心跳信息
void sendHeartbeat(int socket) {
    char heartbeatMsg[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    send(socket, heartbeatMsg, sizeof(heartbeatMsg), 0);
}

// 用socket连接，读取数据包后并解析
void PcapUtils::readSocket() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);

    // 创建套接字文件描述符
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // 强行将套接字连接到8080端口
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(8080);

    // 强行将套接字连接到8080端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    // 从客户端接收数据
    char buffer[1024] = {0};
    read(new_socket, buffer, 1024);
    MDQPHeader mdqpHeader;
    mdqpHeader.parse(buffer); // 调用构造函数构造 mdqpHeader 对象

    // 根据typeID处理不同类型的消息
    switch (mdqpHeader.typeID) {
        case 0x11: // Login request
            // Handle login request
            break;
        case 0x12: // Login response
            // Handle login response
            break;
            // Add cases for other message types
    }
}

// ========== socket

void PcapUtils::readPcapFile() {
    std::cout << "read pcap file" << std::endl;

    char errbuff[PCAP_ERRBUF_SIZE];
    const char *filename = HOME_DIR"data/shfe/shfe_of1_500s_00021_20241115105502.pcap"; // 上期行情pcap文件

    // 打开pcap文件
    pcap_t *pcap = pcap_open_offline(filename, errbuff);
    if (pcap == nullptr) {
        std::cerr << "无法打开文件: " << errbuff << std::endl;
        //return 1;
    }

    // wg - 解 file_header，确定是 pcap 格式的文件
    pcap_file_header pfh = *(pcap_file_header *)filename; // pcap.h 中包含的 pcap头
    PcapFileHeader *file_header = (PcapFileHeader *)filename;
    std::cout << "PcapFileHeader:" << sizeof(PcapFileHeader)
    << " " << file_header->magic << std::endl;

    // 读取和打印 pcap文件中的每个数据包
    const u_char *packet;
    struct pcap_pkthdr *header;
    //struct pcap_pkthdr header; // pcap 包头部
    int i= 0;
    while ((packet = pcap_next(pcap, header)) != nullptr) {
        //std::cout << "得到数据包，长度: " << header.len << " caplen/数据包物理长度: " << header.caplen << " 时间: " << header.ts.tv_sec << "." << header.ts.tv_usec << std::endl;
        // 打印更多的数据包信息
/*        for (int i = 0; i < header.caplen; i++) {
            printf("%02x ", packet[i]); // 以十六进制显示原始载荷数据
        }*/

        //compareTraffic.writeTraffic1(header);
        //CompareTraffic::writeTraffic1(header);
        i++;

        //packet = pcap_next(pcap, &header);

        // ================================
        // 行情解码
        std::cout << "============= 行情解码 ============= " << i << std::endl;
        std::cout << "数据时间戳：" << header->ts.tv_sec << std::endl;
        std::cout << "数据包长度：" << header->len << std::endl;
        std::cout << "有效载荷的长度：" << header->caplen << std::endl;
        //parse_packet(header, packet);

        packet_handler2(header, packet);

        //packet_handler3(header, packet);


    }

    // 关闭 pcap 句柄
    pcap_close(pcap);
    std::cout << "包总数" << i << std::endl;

    //return 0;

}


// 检查是否到达计数起点
bool PcapUtils::checkIsStart(std::chrono::system_clock::time_point startTime, int offset) {
    // 当前时间是否 >= 启动时间 + 偏移时间
    // 获取当前时间作为启动时间
    //return (std::chrono::system_clock::now() >= startTime + std::chrono::seconds(offset)) ? true : false;
    return (std::chrono::system_clock::now() >= startTime + std::chrono::seconds(offset)); // 简化后
}


// 从网络接口读取数据包并解析 = 会报错，对‘pcap_open’未定义的引用
/*int PcapUtils::readNetworkInterface() {
    pcap_if_t *alldevs;
    pcap_t *handle;
    char errbuf[PCAP_ERRBUF_SIZE];
    const unsigned char *packet; // 指向的是包的原始数据载荷
    struct pcap_pkthdr header; // 包头中包含了时间戳、捕获长度和原始数据长度等信息
    int res;

     // 获取网络接口
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
        fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
        return 1;
    }

     // 打开网络接口
    handle = pcap_open(alldevs->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "Couldn't open device %s: %s\n", alldevs->name, errbuf);
        pcap_freealldevs(alldevs);
        return 2;
    }

    pcap_freealldevs(alldevs);

     // 读取并解析网络包
    // pcap_next_ex()函数会阻塞等待，直到捕获到一个网络包或超时
    //if (pcap_loop(handle, 10, packet_handler, reinterpret_cast<u_char*>(&compareTraffic)) < 0)  // pcap_loop()函数会阻塞等待，直到捕获到一个网络包或超时
    while ((res = pcap_next_ex(handle, reinterpret_cast<pcap_pkthdr **>(&header), &packet)) >= 0) {
        if (res == 0)
             // 超时
            continue;

         // 包头信息
        printf("Timestamp: %lld.%lld\n", header.ts.tv_sec, header.ts.tv_usec);
        printf("Caplen: %d\n", header.caplen);
        printf("Len: %d\n", header.len);

         // 有效载荷
        printf("Packet: ");
        for (int i = 0; i < header.caplen; i++) {
            printf("%02x ", packet[i]);
        }
        printf("\n");
    }

    if (res == -1) {
        fprintf(stderr, "Error reading the packets: %s\n", pcap_geterr(handle));
        return 3;
    }

    pcap_close(handle);
    return 0;

}*/


int PcapUtils::readNetworkIface2() {
    char errbuff[PCAP_ERRBUF_SIZE];

    // 基于指定的设备接口创建一个pcap句柄 = 需要root权限，执行时要加 sudo
    pcap_t *pcap = pcap_open_live("ens33", 65536, 1, 1, errbuff);
    if (pcap == nullptr) {
        std::cerr << "无法打开文件: " << errbuff << std::endl;
        return 1;
    }


    // 读取和打印 pcap文件中的每个数据包
    const u_char *packet;
    struct pcap_pkthdr header; // pcap 包头部
    while ((packet = pcap_next(pcap, &header)) != nullptr) {
        std::cout << "得到数据包，长度: " << header.len << " caplen/数据包物理长度: " << header.caplen << " 时间: " << header.ts.tv_sec << "." << header.ts.tv_usec << std::endl;
    }

    // 关闭 pcap 句柄
    pcap_close(pcap);

    return 0;
}

// 参考
// https://blog.csdn.net/xuan196/article/details/135538876
// 从网卡获取
int PcapUtils::readNetworkIfaceLine1(std::chrono::system_clock::time_point startTime, IniReader* iniCfg) {
    // 从配置文件中获取配置
    std::string device = iniCfg->ReadString("LINE_1", "device","");
    std::string sourceIP = iniCfg->ReadString("LINE_1", "sourceIP","");
    std::string destinationIP = iniCfg->ReadString("LINE_1", "destinationIP","");
    std::string destinationPort = iniCfg->ReadString("LINE_1", "destinationPort","");
    std::string filterStr = iniCfg->ReadString("LINE_1", "filterStr","");

    std::string target_time_all = iniCfg->ReadString("MODE", "target_time_all","");

    std::cout << "获取参数" << std::endl;
    std::cout << "device: " << device << std::endl;

    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *handle;

    // 网络接口名称
    const char *dev = device.c_str(); //"ens33";

    // 创建 pcap 句柄
    handle = pcap_create(dev, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "无法创建 pcap 句柄: %s\n", errbuf);
        return 1;
    }

    // 设置纳秒级时间戳精度
    if (pcap_set_tstamp_precision(handle, PCAP_TSTAMP_PRECISION_NANO) != 0) {
        fprintf(stderr, "设置纳秒级时间戳精度失败: %s\n", pcap_geterr(handle));
        // 也可以选择在这里退出，如果纳秒级别时间戳是必需的
    }

    // 激活 pcap 句柄
    if (pcap_activate(handle) != 0) {
        fprintf(stderr, "激活 pcap 句柄失败: %s\n", pcap_geterr(handle));
        pcap_close(handle);
        return 1;
    }

    // 设置过滤器
    struct bpf_program fp;
    char filter_exp2[] = "host 192.168.192.1"; // 过滤IP数据包，等价的写法，c_str 后为 const char *
    const char *filter_exp = filterStr.c_str() ;
    if (pcap_compile(handle, &fp, filter_exp, 0, PCAP_NETMASK_UNKNOWN) < 0) { // 编译过滤器
        fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }
    if (pcap_setfilter(handle, &fp) < 0) { // 应用过滤器
        fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }

    // 检查实际的时间戳精度
    int tstamp_precision = pcap_get_tstamp_precision(handle);

    struct pcap_pkthdr *header;
    const u_char *packet;
    std::cout << "pcap" << std::endl;
    //std::cout << std::chrono::system_clock::now().time_since_epoch() << std::endl;
    //std::cout <<  startTime.time_since_epoch() + std::chrono::seconds(3) << std::endl;
    //sleep(4);
    std::cout <<  (std::chrono::system_clock::now().time_since_epoch() >= startTime.time_since_epoch() + std::chrono::seconds(3)) << std::endl;

    // 计数起点，停止标记不存在

    auto currentTime = std::chrono::system_clock::now();
    // 当前时间小于指定时间，则忙等
    while ( currentTime <= string_to_time_point(target_time_all) ) {
        // 当前时间小于目标时间，等待100毫秒后再次检查
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        currentTime = std::chrono::system_clock::now();
        //std::cout << "1 忙等中。。。" << std::endl;
    }

    std::cout << "1 pcap开始抓取数据包" << std::endl;
    // 捕获循环
    while (pcap_next_ex(handle, &header, &packet) >= 0 ) { // 超时时间
        //std::cout << "得到数据包，长度: " << header->len << " caplen/数据包物理长度: " << header->caplen << " 时间: " << header->ts.tv_sec << "." << header->ts.tv_usec << std::endl;
        //compareTraffic.writeTraffic1(*header);

        // 过滤不到数据时，header 为空指针?
        if ( header == nullptr) {
            std::cout << "数据包为空指针" << std::endl;
        }

/*            // 根据时间戳精度打印时间
            if (tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
                printf("Timestamp: %ld seconds, %ld nanoseconds\n", header->ts.tv_sec, header->ts.tv_usec); // 纳秒级时间戳
            } else {
                printf("Timestamp: %ld seconds, %ld microseconds\n", header->ts.tv_sec, header->ts.tv_usec); // 毫秒级时间戳
            }*/

        // ===================================================
        // 行情解码
        std::cout << "============= 行情解码 =============" << std::endl;
        std::cout << "数据时间戳：" << header->ts.tv_sec << std::endl;
        std::cout << "数据包长度：" << header->len << std::endl;
        std::cout << "有效载荷的长度：" << header->caplen << std::endl;
        parse_packet(header, packet);


    }

    std::cout << "pcap 抓取数据包结束" << std::endl;
    pcap_close(handle);
    return 0;
}


int PcapUtils::readNetworkIfaceLine2(std::chrono::system_clock::time_point startTime, IniReader* iniCfg) {
    // 从配置文件中获取配置
    std::string device = iniCfg->ReadString("LINE_2", "device","");
    std::string sourceIP = iniCfg->ReadString("LINE_2", "sourceIP","");
    std::string destinationIP = iniCfg->ReadString("LINE_2", "destinationIP","");
    std::string destinationPort = iniCfg->ReadString("LINE_2", "destinationPort","");
    std::string filterStr = iniCfg->ReadString("LINE_2", "filterStr","");
    //std::cout << "2 过滤规则 " << filterStr << std::endl;

    std::string target_time_all = iniCfg->ReadString("MODE", "target_time_all","");


    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *handle;

    // 网络接口名称
    const char *dev = device.c_str(); //"ens33";

    // 创建 pcap 句柄
    handle = pcap_create(dev, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "无法创建 pcap 句柄: %s\n", errbuf);
        return 1;
    }

    // 设置纳秒级时间戳精度
    if (pcap_set_tstamp_precision(handle, PCAP_TSTAMP_PRECISION_NANO) != 0) {
        fprintf(stderr, "设置纳秒级时间戳精度失败: %s\n", pcap_geterr(handle));
        // 也可以选择在这里退出，如果纳秒级别时间戳是必需的
    }

    // 激活 pcap 句柄
    if (pcap_activate(handle) != 0) {
        fprintf(stderr, "激活 pcap 句柄失败: %s\n", pcap_geterr(handle));
        pcap_close(handle);
        return 1;
    }

    // 设置过滤器
    struct bpf_program fp;
    const char *filter_exp = filterStr.c_str() ;
    if (pcap_compile(handle, &fp, filter_exp, 0, PCAP_NETMASK_UNKNOWN) < 0) {
        fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }
    if (pcap_setfilter(handle, &fp) < 0) {
        fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }

    // 检查实际的时间戳精度
    int tstamp_precision = pcap_get_tstamp_precision(handle);

    struct pcap_pkthdr *header;
    const u_char *packet;


    // 计数起点，停止标记不存在

    auto currentTime = std::chrono::system_clock::now();
    // 当前时间小于指定时间，则忙等
    //while (currentTime.time_since_epoch() <= startTime.time_since_epoch() + std::chrono::seconds(5)) {
    while ( currentTime <= string_to_time_point(target_time_all) ) {
        // 当前时间小于目标时间，等待100毫秒后再次检查
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        currentTime = std::chrono::system_clock::now();
        //std::cout << "2 忙等中。。。" << std::endl;
    }

    std::cout << "2 pcap开始抓取数据包" << std::endl;
    // 捕获循环
    while (pcap_next_ex(handle, &header, &packet) >= 0) {
        //std::cout << "得到数据包，长度: " << header->len << " caplen/数据包物理长度: " << header->caplen << " 时间: " << header->ts.tv_sec << "." << header->ts.tv_usec << std::endl;
        compareTraffic.writeTraffic2(*header);
    }
    pcap_close(handle);
    return 0;
}

// 从网卡获取
// pcap_loop(fp, 0, dispatcher_handler, (u_char*)this); // 捕获数据包，并传递给回调函数处理
int PcapUtils::readNetworkIface4() {
    pcap_t* handle = nullptr;
    char errbuf[PCAP_ERRBUF_SIZE];
    const int timeout = 10; // 捕获数据包的超时时间（毫秒）

    printf("pcap_open_live\n");
    handle = pcap_open_live("ens33", 4 * BUFSIZ, 1, timeout, errbuf);
    if (handle == NULL) {
        printf("Couldn't open device\n");
        return -1;
    }

    //std::string str_filter = "ip dst host " + std::string(mc_ip) + " and dst port " + std::to_string(mc_port);
    std::string str_filter = "" ; // "ip dst host 10.0.2.2 and src port 29375";
    struct bpf_program fp;
    printf("pcap_compile\n");
    if (pcap_compile(handle, &fp, str_filter.c_str(), 0, PCAP_NETMASK_UNKNOWN) == -1) {
        printf("Couldn't parse filter\n");
        return -1;
    }
    printf("pcap_setfilter\n");
    if (pcap_setfilter(handle, &fp) == -1) {
        printf("Couldn't install filter \n");
        return -1;
    }

    // 包捕获的回调函数
    auto packet_handler = [](u_char *user_data, u_char* temp, const struct pcap_pkthdr* header, const u_char* pkt_data) -> void
    {
        // user_data 可以用于传递用户数据，这里传递的是 CompareTraffic 对象的指针
        CompareTraffic *compareTraffic = reinterpret_cast<CompareTraffic*>(user_data);
        IPv4Header ipv4(pkt_data);

        printf("%s.%lu SrcIP:%s, DstIP:%s\n", Stamp2Time(header->ts.tv_sec).c_str(), header->ts.tv_usec, ipv4.SrcIP.c_str(), ipv4.DstIP.c_str());
        sleep(1);
        compareTraffic->writeTraffic1(*header);
    };

    struct PacketHandlerArgs {
        u_char* temp;
        const struct pcap_pkthdr* header;
        const u_char* pkt_data;
        CompareTraffic compareTraffic;
    };
    struct PacketHandlerArgs args;
    args.temp = (u_char*)this;
    args.compareTraffic = compareTraffic;

    // 使用 pcap_loop 捕获数据包
    // reinterpret_cast<u_char*>(&compareTraffic)   (u_char*)&args
/*    if (pcap_loop(handle, -1, packet_handler, reinterpret_cast<u_char*>(&compareTraffic) ) < 0) {
        fprintf(stderr, "pcap_loop failed: %s\n", pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }*/

    // pcap_loop和callback之间参数存在联系，pcap_loop的最后一个参数user是留给用户使用的，当callback被调用的时候这个值会传递给callback的第一个参数(也叫user)，
    // callback的最后一个参数p指向一块内存空间，这个空间中存放的就是pcap_loop抓到的数据包

    printf("pcap_close\n");
    pcap_close(handle);
}


// 读队列
int PcapUtils::readMsg(std::shared_ptr<spdlog::logger> _my_logger, IniReader* iniCfg) {
    //std::cout << "readMsg" << std::endl;
    my_logger->info("readMsg");
    compareTraffic.readTraffic1(my_logger);
    return 0;
}

// 采样统计
int PcapUtils::sampled(std::shared_ptr<spdlog::logger> _my_logger, IniReader* iniCfg) {
    //std::cout << "readMsg" << std::endl;
    my_logger->info("采样统计");
    compareTraffic.sampledAndSave(my_logger);
    return 0;
}



// 解析时间字符串并转换为 time_point =
// tm ---> time_t ---> time_point
/*std::chrono::system_clock::time_point PcapUtils::parseTime(const std::string& timeStr) {
    std::tm tm = {};
    std::istringstream ss(timeStr);

    // 使用 std::get_time 解析时间字符串
    ss << std::get_time(&tm, "%Y-%m-%d %H:%M:%S");

    if (ss.fail()) {
        throw std::runtime_error("Failed to parse time string");
    }

    // 将 struct tm 转换为 time_t
    std::time_t time_t_value = mktime(&tm);

    // 将 time_t 转换为 system_clock::time_point
    auto duration = std::chrono::system_clock::from_time_t(time_t_value);

    // 处理纳秒部分
    std::string nanosecondsStr = timeStr.substr(20);
    std::istringstream nsStream(nanosecondsStr);
    long long nanoseconds;
    nsStream >> nanoseconds;

    // 将纳秒部分添加到 duration
    duration += std::chrono::nanoseconds(nanoseconds);

    return duration;
}*/


// 将时间字符串转换为 time_point
std::chrono::system_clock::time_point PcapUtils::string_to_time_point(const std::string& str) {
    // 解析字符串
    int year, month, day, hour, minute, second;
    std::istringstream ss(str);
    char delimiter;

    ss >> year >> delimiter >> month >> delimiter >> day >> delimiter
       >> hour >> delimiter >> minute >> delimiter >> second;

    // 创建 tm 结构体
    std::tm tm_struct = {};
    tm_struct.tm_year = year - 1900; // 年份从 1900 开始计算
    tm_struct.tm_mon = month - 1;     // 月份从 0 开始计算
    tm_struct.tm_mday = day;
    tm_struct.tm_hour = hour;
    tm_struct.tm_min = minute;
    tm_struct.tm_sec = second;

    // 转换为 time_t
    std::time_t time_t_value = mktime(&tm_struct);

    // 转换为 time_point
    return std::chrono::system_clock::from_time_t(time_t_value);
}

// 解析数据包 = 使用自定义的数据结构体
void PcapUtils::parse_packet(const struct pcap_pkthdr* pkthdr, const u_char* packet) {
    // 解析以太网头部
    struct my_ether_header *eth_hdr = (struct my_ether_header *)packet;
    std::cout << "eth_hdr->ether_shost: " << eth_hdr->ether_shost << std::endl;
    std::cout << "eth_hdr->ether_dhost: " << eth_hdr->ether_dhost << std::endl;
    std::cout << "std::hex << eth_hdr->ether_shost: " << std::hex << eth_hdr->ether_shost << std::endl;
    std::cout << "eth_hdr->ether_type: " << eth_hdr->ether_type << std::endl;
    std::cout << "ntohs(eth_hdr->ether_type): " << ntohs(eth_hdr->ether_type) << std::endl;
    if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP ) { // ntohs 将网络字节序转换为主机字节序
        // 解析IP头部
        struct my_ip_header *ip_hdr = (struct my_ip_header *)(packet + sizeof(struct my_ether_header));
        if (ip_hdr->ip_p == IPPROTO_TCP) {
            // 解析TCP头部
            struct my_tcp_header *tcp_hdr = (struct my_tcp_header *)(packet + sizeof(struct my_ether_header) + (ip_hdr->ip_hl * 4));

            // 计算payload的起始位置
            int payload_offset = sizeof(struct my_ether_header) + (ip_hdr->ip_hl * 4) + (tcp_hdr->th_off * 4);
            int payload_size = pkthdr->len - payload_offset;

            // 打印基本信息
            printf("Source IP: %s\n", inet_ntoa(ip_hdr->ip_src));
            printf("Destination IP: %s\n", inet_ntoa(ip_hdr->ip_dst));
            printf("Source Port: %d\n", ntohs(tcp_hdr->th_sport));
            printf("Destination Port: %d\n", ntohs(tcp_hdr->th_dport));
            printf("Payload Size: %d bytes\n", payload_size);

            // 以十六进制打印 payload
            if (payload_size > 0) {
                printf("Payload:\n");
                for (int i = 0; i < payload_size; ++i) {
                    printf("%02x ", packet[payload_offset + i]); // 在每行打印 16 个字节的数据，每个字节以两位十六进制数的形式输出
                    if ((i + 1) % 16 == 0) { // 每打印 16 个字节后换行
                        printf("\n");
                    }
                }
                printf("\n");
            }
        }
    }
}


// 回调函数，处理每个捕获的数据包 = 使用内库中的数据结构体
void PcapUtils::packet_handler2(const struct pcap_pkthdr *pkthdr, const u_char *packet) {
    std::cout << "---------" << std::endl;

    // 解析以太网帧头部 = 14字节
    const struct ether_header *eth_header = (struct ether_header *)(packet);
    std::cout << "ether_type: " << eth_header->ether_type << std::endl; // 0x0800 = ipv4
    // 跳过以太网帧头部
    std::cout << "以太头部1: " << sizeof(struct ether_header) << std::endl;
    std::cout << "以太头部2: " << sizeof(&eth_header) << std::endl;
    packet += sizeof(struct ether_header); // eth 14 字节
    std::cout << "剩余长度: " << sizeof(&packet) << std::endl;

    // 获取 IP 头部 = 20字节
    const struct ip *ip_header = (struct ip *)(packet); // 以太网头部长度为 14 字节
    const struct my_ip_header *my_ip_header = (struct my_ip_header *)(packet); // 以太网头部长度为 14 字节

    printf("ip_header长度: %d\n", sizeof(ip_header));
    printf("my_ip_header长度: %d\n", sizeof(my_ip_header));
    printf("source ip: %d\n", ip_header->ip_src);
    printf("dest ip: %d\n", ip_header->ip_dst);
    printf("总长度: %d\n", ntohs(ip_header->ip_len));
    printf("校验和: %d\n", ntohs(ip_header->ip_sum));

    if (ip_header->ip_p == IPPROTO_TCP) {
        printf("tcp\n");
        //return; // 不是 TCP 协议，跳过
        handleTcp(pkthdr,packet);
    } else if (ip_header->ip_p == IPPROTO_UDP) {
        printf("udp\n");
        //PcapUtils::handleUdp(pkthdr,packet);
        handleUdp(pkthdr,packet);
    }

/*    // 获取 TCP 头部 = 14 + ip头部长度*4字节
    const struct my_tcp_header *tcp_header = (struct my_tcp_header *)(packet + 14 + (ip_header->ip_hl * 4)); // IP 头部总长度？

    // 打印源端口和目的端口
    printf("Source Port: %d\n", ntohs(tcp_header->th_sport));
    printf("Destination Port: %d\n", ntohs(tcp_header->th_dport));

    // 打印源 IP 地址和目的 IP 地址
    printf("Source IP: %s\n", inet_ntoa(ip_header->ip_src));
    printf("Destination IP: %s\n", inet_ntoa(ip_header->ip_dst));

    // 打印数据包长度
    printf("Packet Length: %d bytes\n", pkthdr->len);

    printf("\n");

    // 以十六进制打印 payload
    // 计算payload的起始位置
    int payload_offset = sizeof(struct my_ether_header) + (ip_header->ip_hl * 4) + (tcp_header->th_off * 4);
    int payload_size = pkthdr->len - payload_offset;
    if (payload_size > 0) {
        printf("Payload:\n");
        for (int i = 0; i < payload_size; ++i) {
            printf("%02x ", packet[payload_offset + i]); // 在每行打印 16 个字节的数据，每个字节以两位十六进制数的形式输出
            if ((i + 1) % 16 == 0) { // 每打印 16 个字节后换行
                printf("\n");
            }
        }
        printf("\n");
    }*/
}

void PcapUtils::packet_handler3(const struct pcap_pkthdr *pkthdr, const u_char *packet) {
    // 解析以太网帧头部
    const struct ether_header *eth_header = (struct ether_header *)packet;

    // 跳过以太网帧头部
    packet += sizeof(struct ether_header);

    // 解析 IP 头部
    const struct ip *ip_header = (struct ip *)packet;

    // 跳过 IP 头部
    packet += (ip_header->ip_hl * 4);

    // 解析 TCP 头部
    const struct tcphdr *tcp_header = (struct tcphdr *)packet;

    // 获取 TCP 头部长度（以字节为单位）
    //int tcp_header_length = (tcp_header->th_off * 4);

    // 打印 TCP 头部长度
    //std::cout << "TCP Header Length: " << tcp_header_length << " bytes" << std::endl;
}

void PcapUtils::handleTcp(const struct pcap_pkthdr *pkthdr, const u_char *packet) {
    // 解析以太网帧头部 = 14字节
    //const struct ether_header *eth_header = (struct ether_header *)packet;
    // 跳过以太网帧头部
    //packet += sizeof(struct ether_header);

    auto ss = std::string(packet, packet + 14); // 前14个字节
    auto sa = sizeof(packet);
    printf("ss: %s\n", ss.c_str());
    printf("-------------sa: %d\n", sa);

    // 获取 IP 头部 = 20字节
    const struct ip *ip_header = (struct ip *)(packet); // ip 20 字节
    if (ip_header->ip_p != IPPROTO_TCP) {
        printf("no tdp\n");
        return; // 不是 TCP 协议，跳过
    }

    // 获取 TCP 头部 = 14 + ip头部长度*4字节
    const struct my_tcp_header *tcp_header = (struct my_tcp_header *)(packet + 20 + (ip_header->ip_hl * 4)); // IP 头部总长度？

    // 打印源端口和目的端口
    printf("Source Port: %d\n", ntohs(tcp_header->th_sport));
    printf("Source Port: %d\n", tcp_header->th_sport);
    printf("th_off*4: %d\n", tcp_header->th_off * 4); // 获取 TCP 头部长度（以字节为单位）
    printf("Destination Port: %d\n", ntohs(tcp_header->th_dport));

    // 打印源 IP 地址和目的 IP 地址
    printf("Source IP: %s\n", inet_ntoa(ip_header->ip_src));
    printf("Destination IP: %s\n", inet_ntoa(ip_header->ip_dst));

    printf("th_flags: %d\n", tcp_header->th_flags);

    // 打印数据包长度
    printf("Packet Length: %d bytes\n", pkthdr->len); // 报文总长度，长度 > 60 的才是有效报文

    std::cout << "---------- 222 ---------" << sizeof(struct my_tcp_header) << " " << sizeof(struct tcphdr) << std::endl;

    // 检查是否为 TCP 报文
    struct tcphdr *tcp_header2 = (struct tcphdr *)(packet + 20 + ip_header->ip_hl * 4); //
    if (ip_header->ip_p == IPPROTO_TCP) {
        printf("TCP Packet:\n");
        //printf("Source IP: %s\n", inet_ntoa(*(struct in_addr *)&ip_header->ip_src));
        //printf("Source IP: %s\n", *(struct in_addr *)&ip_header->ip_src);
        //printf("Destination IP: %s\n", inet_ntoa(*(struct in_addr *)&ip_header->ip_dst));
        printf("Source Port: %d\n", ntohs(tcp_header2->source));
        printf("Destination Port: %d\n", ntohs(tcp_header2->dest));
        printf("seq 序列号: %u\n", ntohl(tcp_header2->seq)); // seq 序列号
        printf("确认号: %u\n", ntohl(tcp_header2->ack_seq)); // 确认号
        printf("Flags: ");

        if (tcp_header2->fin) printf("FIN ");
        if (tcp_header2->syn) printf("SYN ");
        if (tcp_header2->rst) printf("RST ");
        if (tcp_header2->psh) printf("PSH ");
        if (tcp_header2->ack) printf("ACK ");
        if (tcp_header2->urg) printf("URG ");
        if (tcp_header2->res1) printf("res1 ");
        if (tcp_header2->res2) printf("res2 ");
        std::cout << "\ntcp 段" << std::endl;
    }

    if (pkthdr->len >= 60) { // tcp报头 = ip/20 + tcp/60
        std::cout << "---------- 报文长度>=60的为有效报文 ---------" << std::endl;
    }

    // 以十六进制打印 payload
    // 计算payload的起始位置
    int tcp_offset = 0; // tcp 头部的可变部分
    int payload_size = pkthdr->len - 20 - 20 - 20 - tcp_offset; // tcp 头部 = 固定20 + 可变[0-40]
    if (payload_size > 0) {
        printf("Payload:\n");
        for (int i = 0; i < payload_size; ++i) {
            printf("%02x ", packet[20 + tcp_offset + i]); // 在每行打印 16 个字节的数据，每个字节以两位十六进制数的形式输出
            if ((i + 1) % 16 == 0) { // 每打印 16 个字节后换行
                printf("\n");
            }
        }
        printf("\n");
    }
}


void PcapUtils::handleUdp(const struct pcap_pkthdr *pkthdr, const u_char *packet) {
    // 解析以太网帧头部 = 14字节
    //const struct ether_header *eth_header = (struct ether_header *)packet;
    // 跳过以太网帧头部
    //packet += sizeof(struct ether_header);

    // 获取 IP 头部 = 20字节
    const struct ip *ip_header = (struct ip *)(packet); // ip 20 字节
    if (ip_header->ip_p != IPPROTO_UDP) {
        printf("no udp\n");
        //return; // 不是 TCP 协议，跳过
    }

    packet += sizeof(struct ip);

    // 获取 TCP 头部 = 14 + ip头部长度*4字节
    //const struct udphdr *udp_header = (struct udphdr *)(packet + 14 + (ip_header->ip_hl * 4)); // IP 头部总长度？
    const struct udphdr *udp_header = (struct udphdr *)(packet + 14 + (ip_header->ip_hl * 4)); // udp 头部总长度
    std::cout << "udphdr 长度: " << sizeof(struct udphdr) << std::endl;

    // 打印源端口和目的端口
    printf("Source Port: %d\n", ntohs(udp_header->source));
    printf("Source Port: %d\n", udp_header->source);
    printf("Destination Port: %d\n", ntohs(udp_header->dest));

    // 打印源 IP 地址和目的 IP 地址
    printf("Source IP: %s\n", inet_ntoa(ip_header->ip_src));
    printf("Destination IP: %s\n", inet_ntoa(ip_header->ip_dst));

    // 打印数据包长度
    printf("Packet Length: %d bytes\n", pkthdr->len);
    printf("剩余数据报长度: %d bytes\n", ntohs(udp_header->len));

    printf("\n");

    // 以十六进制打印 payload
    // 计算payload的起始位置
    int payload_offset = 8; // 字节数
    int payload_size1 = pkthdr->len - 20 - 20 - payload_offset; // tcp 头部 = 固定20 + 可变[0-40]
    int payload_size = pkthdr->len - sizeof(my_ether_header) - sizeof(my_ip_header) - 8; // 总字节数 - 已解析的报头字节数/tch + ip + udp
    if (payload_size > 0) {
        printf("Payload:\n");
        for (int i = 0; i < payload_size; ++i) {
            printf("%02x ", packet[payload_offset + i]); // 在每行打印 16 个字节的数据，每个字节以两位十六进制数的形式输出
            if ((i + 1) % 16 == 0) { // 每打印 16 个字节后换行
                printf("\n");
            }
        }
        std::cout << "------" << std::endl;
    }

    packet += sizeof(my_ether_header) + sizeof(my_ip_header) + 8;
    // 解析行情
    const struct MIRP_Header *my_MIRP_Header = (struct MIRP_Header *)(packet, packet + 24);
    std::cout << "MIRP_Header->Flag " << ntohs(my_MIRP_Header->Flag) << std::endl;
    std::cout << "MIRP_Header->TypeID " << ntohs(my_MIRP_Header->TypeID) << std::endl;
    printPacket(packet, 100, 0);

    //const struct udphdr *udp_header = (struct udphdr *)(packet + 14 + (ip_header->ip_hl * 4)); // udp 头部总长度
    const struct domain_s *my_domain_s = (struct domain_s *)(packet[48, 48+4]);
    std::cout << "my_domain_s " << sizeof(domain_s) << std::endl; // 4
    std::cout << "MIRP_Header " << sizeof(MIRP_Header) << std::endl; // 24
    printf("%02x ", packet[48, 48+4]);
    std::cout << "\n------\n" << std::endl;
    //std::cout << "FieldID" << my_domain_s->FieldID << std::endl;
    //std::cout << "FieldSize" << my_domain_s->FieldSize << std::endl;

    //memcpy(my_domain_s, packet[48, 48+4], sizeof(struct domain_s));

}

// 以16进制类型打印网络数据包
// 包，长度，偏移量
void PcapUtils::printPacket(const u_char *packet, int payload_size, int payload_offset) {
    for (int i = 0; i < payload_size; ++i) {
        printf("%02x ", packet[payload_offset + i]); // 在每行打印 16 个字节的数据，每个字节以两位十六进制数的形式输出
        if ((i + 1) % 16 == 0) { // 每打印 16 个字节后换行
            printf("\n");
        }
    }
}



// parsePacket 函数接收一个指向网络数据缓冲区的指针和数据长度。
// 使用memcpy来按照Packet结构体中定义的顺序提取数据，并使用网络字节序转换函数（如ntohl和ntohs）来转换字段到主机字节序，以便进一步处理
// memcpy 是 C++ 标准库中的函数，用于在内存之间复制一定数量的字节
// 接收一段数据和一个结构体，将数据拷贝进结构体，实现网络数据的解析
struct Packet {
    uint32_t id;
    uint16_t length;
    char data[256];
};

void parsePacket(const char* buffer, size_t length) {
    if (length < sizeof(Packet)) {
        std::cerr << "Invalid packet length" << std::endl;
        return;
    }

    Packet packet;
    memcpy(&packet.id, buffer, sizeof(packet.id));
    buffer += sizeof(packet.id);
    memcpy(&packet.length, buffer, sizeof(packet.length));
    buffer += sizeof(packet.length);
    size_t dataLength = ntohs(packet.length);
    if (dataLength > sizeof(packet.data)) {
        std::cerr << "Data too large" << std::endl;
        return;
    }
    memcpy(packet.data, buffer, dataLength);

    // 处理解析后的数据
    std::cout << "ID: " << ntohl(packet.id) << ", Length: " << ntohs(packet.length) << ", Data: " << packet.data << std::endl;
}


// ============================================================
// 解析以太网帧头部
void parse_ethernet_header(const u_char *packet, struct ether_header *eth_header) {
    memcpy(eth_header, packet, sizeof(struct ether_header));
}

// 解析 IP 头部
void parse_ip_header(const u_char *packet, struct ip *ip_header) {
    memcpy(ip_header, packet, sizeof(struct ip));
}

// 解析 UDP 头部
void parse_udp_header(const u_char *packet, struct udphdr *udp_header) {
    memcpy(udp_header, packet, sizeof(struct udphdr));
}


// =================================== pcap 解析协议栈，获取有效载荷
void PcapUtils::packet_handler4(u_char *user_data, const struct pcap_pkthdr *pkthdr, const u_char *packet) {
    (void)user_data; // 忽略 user_data 参数

    // 解析以太网帧
    struct ether_header *eth = (struct ether_header *)packet;
    if (ntohs(eth->ether_type) != ETHERTYPE_IP) { // 只处理 IPv4 数据包
        return;
    }

    // 解析 IP 头
    struct ip *iph = (struct ip *)(packet + sizeof(struct ether_header));
    unsigned int ip_header_length = iph->ip_hl * 4;

    // 解析传输层头部
    void *transport_layer = (void *)(packet + sizeof(struct ether_header) + ip_header_length);

    switch (iph->ip_p) {
        case IPPROTO_TCP: {
            struct tcphdr *tcph = (struct tcphdr *)transport_layer;
            unsigned int tcp_header_length = tcph->doff * 4; // th_off

            // 计算有效载荷的起始位置
            char *payload = (char *)tcph + tcp_header_length;
            size_t payload_length = pkthdr->len - sizeof(struct ether_header) - ip_header_length - tcp_header_length;

            std::cout << "TCP Packet: "
                      << inet_ntoa(iph->ip_src) << ":" << ntohs(tcph->source) << " -> " // th_sport
                      << inet_ntoa(iph->ip_dst) << ":" << ntohs(tcph->dest) // th_dport
                      << ", Seq: " << ntohl(tcph->seq) // th_seq
                      << ", Ack: " << ntohl(tcph->ack) // th_ack
                      << ", Flags: " << (unsigned short)ntohs(tcph->fin) // th_flags
                      << ", res1: " << (unsigned short)tcph->res1
                      << ", res2: " << (unsigned short)tcph->res2
                      << ", ack_seq: " << (unsigned short)tcph->ack_seq
                      << ", check: " << (unsigned short)ntohs(tcph->check)
                      << ", psh: " << (unsigned short)tcph->psh
                      << ", window: " << (unsigned short)ntohs(tcph->window)
                      << std::endl;

            if (payload_length > 0) {
                std::cout << "Payload (" << payload_length << " bytes): ";
                for (size_t i = 0; i < payload_length && i < 32; ++i) { // 打印前32个字节
                    printf("%02x ", (unsigned char)payload[i]);
                }
                if (payload_length > 32) {
                    std::cout << "..."; // 如果有更多数据，显示省略号
                }
                std::cout << std::endl;
            }
            break;
        }
        case IPPROTO_UDP: {
            struct udphdr *udph = (struct udphdr *)transport_layer;
            size_t udp_header_length = sizeof(struct udphdr);
            size_t payload_length = pkthdr->len - sizeof(struct ether_header) - ip_header_length - udp_header_length;

            // 计算有效载荷的起始位置
            char *payload = (char *)udph + udp_header_length;

            std::cout << "UDP Packet: "
                      << inet_ntoa(iph->ip_src) << ":" << ntohs(udph->source) << " -> "
                      << inet_ntoa(iph->ip_dst) << ":" << ntohs(udph->dest)
                      << ", Length: " << ntohs(udph->len)
                      << std::endl;

            if (payload_length > 0) {
                std::cout << "Payload (" << payload_length << " bytes): ";
                for (size_t i = 0; i < payload_length && i < 32; ++i) { // 打印前32个字节
                    printf("%02x ", (unsigned char)payload[i]);
                }
                if (payload_length > 32) {
                    std::cout << "..."; // 如果有更多数据，显示省略号
                }
                std::cout << std::endl;
            }
            break;
        }
        default:
            std::cout << "Other Protocol: " << (int)iph->ip_p << std::endl;
            break;
    }
}

// 主函数
int PcapUtils::packet_handler4Main() {
    const char *pcap_file = HOME_DIR"data/shfe/enp179s0f1_head_1m.pcap";
    char errbuf[PCAP_ERRBUF_SIZE];

    // 打开 .pcap 文件
    pcap_t *handle = pcap_open_offline(pcap_file, errbuf);
    if (handle == nullptr) {
        std::cerr << "Error opening pcap file: " << errbuf << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "读取 pcap 文件 " << pcap_file << "..." << std::endl;

    // 定义 BPF 过滤表达式 = BPF 过滤器在内核级别过滤数据包，减少了用户空间的处理负担，从而提高了性能
    const char *bpf_filter = ""; // host 192.168.12.73

    // 编译 BPF 过滤器
    struct bpf_program filter;
    bzero(&filter, sizeof(filter));

    if (pcap_compile(handle, &filter, bpf_filter, 1, PCAP_NETMASK_UNKNOWN) == -1) {
        std::cerr << "Error compiling BPF filter: " << pcap_geterr(handle) << std::endl;
        pcap_close(handle);
        return EXIT_FAILURE;
    }

    // 应用 BPF 过滤器
    if (pcap_setfilter(handle, &filter) == -1) {
        std::cerr << "Error setting BPF filter: " << pcap_geterr(handle) << std::endl;
        pcap_freecode(&filter); // 释放编译后的过滤器
        pcap_close(handle);
        return EXIT_FAILURE;
    }

    // 释放编译后的过滤器
    pcap_freecode(&filter);

    // 读取并解析数据包
    pcap_loop(handle, 0, packet_handler4, nullptr);

    // 关闭 pcap 文件
    pcap_close(handle);

    return 0;
}
















